﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using Cms.Domain;
using Cms.Web.Framework.Infrastructure.Wrappers;

namespace Cms.Web.Framework.Infrastructure
{
    public class UrlRewriterHandler
    {
        private readonly RequestDetails _requestDetails;
        private readonly ICmsHttpContext _httpContext;
        private readonly ICmsFormsAuthentication _formsAuthentication;
        private readonly ICmsHttpContextItems _httpContextItems;
        private readonly ICmsIdentity _identity;
        private readonly ICmsCache _cache;
        private string _rewriteUrl;

        #region Private Properties

        private bool RequestIsPage
        {
            get { return _requestDetails.GetPage(); }
        }

        private bool RequestIsCachedMediaFile
        {
            get { return _cache.Get(_requestDetails.FoldersAndPage) != null; }
        }

        private bool RequestIsSystemPage
        {
            get { return _requestDetails.IsSystemPageRequest(); }
        }

        private bool AdministratorMustBeLoggedOut
        {
            get { return _identity.IsAuthenticated && _requestDetails.AdministratorMustBeLoggedOut; }
        }

        private bool SiteIsFound
        {
            get { return _requestDetails.Site != null; }
        }

        private bool RequestIsMediaFile
        {
            get { return _requestDetails.IsMediaFile(); }
        }

        private bool RequestIsRssFeed
        {
            get { return _requestDetails.IsRssFeed(); }
        }

        private void SignOutAdministrator()
        {
            _formsAuthentication.SignOut();
            _rewriteUrl = "~/Admin/Default.aspx";
        }

        #endregion

        public UrlRewriterHandler(
            RequestDetails requestDetails,
            ICmsHttpContext httpContext,
            ICmsFormsAuthentication formsAuthentication,
            ICmsHttpContextItems httpContextItems,
            ICmsIdentity identity,
            ICmsCache cache)
        {
            _requestDetails = requestDetails;
            _httpContext = httpContext;
            _formsAuthentication = formsAuthentication;
            _httpContextItems = httpContextItems;
            _identity = identity;
            _cache = cache;
            _rewriteUrl = _requestDetails.RequestedUrl;
        }

        public void AuthorizeRequest()
        {
            if (RequestIsCachedMediaFile)
            {
                return;
            }
            if (RequestIsSystemPage)
            {
                if (AdministratorMustBeLoggedOut)
                {
                    SignOutAdministrator();
                }
            }
            else
            {
                ResolveRequestForPublicAsset();
            }
            FinishRequest();
        }

        #region Private Methods

        private void ResolveRequestForPublicAsset()
        {
            ResolveSiteAndLocale();
            SetCulture();
            if (!SiteIsFound)
            {
                return;
            }
            if (RequestIsMediaFile)
            {
                InsertCacheHandleForMediaFileOutputCache();
                _rewriteUrl = "~/MediaHandler.aspx?file=" + HttpUtility.UrlEncode(_requestDetails.RequestedUrl);
                return;
            }
            if (RequestIsRssFeed)
            {
                _rewriteUrl = "~/RssHandler.aspx?feed=" + HttpUtility.UrlEncode(_requestDetails.PageFilename);
                if (!string.IsNullOrEmpty(_requestDetails.QueryString))
                {
                    _rewriteUrl += "&" + _requestDetails.QueryString;
                }
                return;
            }
            if (!RequestIsPage)
            {
                return;
            }
            ResolvePageRewriteUrl();
        }

        private void ResolvePageRewriteUrl()
        {
            _rewriteUrl = _requestDetails.Page is ApplicationPage
                              ? "~/__System/ApplicationPages/" + _requestDetails.Page.ID + ".aspx?" + _requestDetails.QueryString
                              : "~/page.aspx?id=" + _requestDetails.Page.ID;
        }

        private void InsertCacheHandleForMediaFileOutputCache()
        {
            _cache.Insert(
                _requestDetails.FoldersAndPage,
                true,
                int.Parse(ConfigurationManager.AppSettings["MediaOutputCacheDuration"]));
        }

        private void FinishRequest()
        {
            _httpContextItems.Update("RequestDetails", _requestDetails);
            if (_rewriteUrl != _requestDetails.RequestedUrl)
            {
                _httpContext.RewritePath(_rewriteUrl);
            }
        }

        private void ResolveSiteAndLocale()
        {
            _requestDetails.ResolveSiteAndLocale();
        }

        private void SetCulture()
        {
            if (_requestDetails.Locale == null || string.IsNullOrEmpty(_requestDetails.Locale.CultureCode))
            {
                return;
            }
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(_requestDetails.Locale.CultureCode);
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(_requestDetails.Locale.CultureCode, true);
        }

        #endregion
    }
}
